<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="ZkkJm" id="ZkkJm"><span data-lake-id="ue9327f24" id="ue9327f24">典型回答</span></h1>
  <p data-lake-id="u2daacdbc" id="u2daacdbc"><br></p>
  <p data-lake-id="u76365b6e" id="u76365b6e"><br></p>
  <p data-lake-id="u186d803f" id="u186d803f"><span data-lake-id="ub2c2ed19" id="ub2c2ed19">上一篇文章中介绍了关于看门狗的机制，他会在用户没有指定锁的超时时间的时候，给锁做续期，他会有一个后台线程，定时的给锁续期。</span></p>
  <p data-lake-id="u6f4819ea" id="u6f4819ea"><span data-lake-id="uc3719316" id="uc3719316">​</span><br></p>
  <p data-lake-id="u8e3451c7" id="u8e3451c7"><span data-lake-id="u34d283dc" id="u34d283dc">因为watch dog的续期，是没有次数和时长的限制的，也就是说，如果没有主动解锁，那么他就会一直续期下去。</span></p>
  <p data-lake-id="u0b12f18a" id="u0b12f18a"><span data-lake-id="ud85d8936" id="ud85d8936">​</span><br></p>
  <p data-lake-id="u5c9f00ba" id="u5c9f00ba"><span data-lake-id="u9e6341b0" id="u9e6341b0">那么，就会有人提出这样的问题：</span></p>
  <p data-lake-id="u9ce3275d" id="u9ce3275d"><span data-lake-id="u0f139c19" id="u0f139c19">​</span><br></p>
  <p data-lake-id="u52f8d9e8" id="u52f8d9e8"><span data-lake-id="ufdaf4be5" id="ufdaf4be5">1、一直续期，别人不是拿不到锁了吗？</span></p>
  <p data-lake-id="ucc913da6" id="ucc913da6"><span data-lake-id="uec0ae452" id="uec0ae452">2、一旦客户端挂了但是锁还没释放怎么办？</span></p>
  <p data-lake-id="u319c6ee1" id="u319c6ee1"><span data-lake-id="u844d04de" id="u844d04de">3、如果解锁失败了，怎么办？</span></p>
  <p data-lake-id="uc8218473" id="uc8218473"><span data-lake-id="u4f974a46" id="u4f974a46">​</span><br></p>
  <h3 data-lake-id="OQ2JK" id="OQ2JK"><span data-lake-id="ub0c2f066" id="ub0c2f066">一直续期，别人不是拿不到锁了吗？</span></h3>
  <p data-lake-id="u1c8ee9a1" id="u1c8ee9a1"><span data-lake-id="u0ec7fcee" id="u0ec7fcee">​</span><br></p>
  <p data-lake-id="uc137f33e" id="uc137f33e"><span data-lake-id="u1a85997c" id="u1a85997c">上面这两个问题你可能不知道答案，那下面这几个你一定知道答案：</span></p>
  <p data-lake-id="uff71a5dc" id="uff71a5dc"><span data-lake-id="ucba234d7" id="ucba234d7">​</span><br></p>
  <p data-lake-id="udc01e576" id="udc01e576"><span data-lake-id="u526b3d9b" id="u526b3d9b">分布式锁的目的是什么？防止并发。</span></p>
  <p data-lake-id="ucfa65e22" id="ucfa65e22"><span data-lake-id="ue9da1d6d" id="ue9da1d6d">​</span><br></p>
  <p data-lake-id="u534a799c" id="u534a799c"><span data-lake-id="u3188d974" id="u3188d974">锁续期的条件是什么？还没解锁。</span></p>
  <p data-lake-id="uf7b7d710" id="uf7b7d710"><span data-lake-id="u74d09d15" id="u74d09d15">​</span><br></p>
  <p data-lake-id="u4b57683c" id="u4b57683c"><span data-lake-id="u7674ea8c" id="u7674ea8c">什么情况下会没解锁？任务没执行完。</span></p>
  <p data-lake-id="uff27eed8" id="uff27eed8"><span data-lake-id="u496b1847" id="u496b1847">​</span><br></p>
  <p data-lake-id="u4617b056" id="u4617b056"><span data-lake-id="uf2e90806" id="uf2e90806">那么，如果一个任务没执行完，我就一直给他续期，让他不断地延长锁时长，防止并发，有毛病吗？没有啊！</span></p>
  <p data-lake-id="u8f56d682" id="u8f56d682"><span data-lake-id="u03118477" id="u03118477">​</span><br></p>
  <p data-lake-id="u8709794c" id="u8709794c"><span data-lake-id="uc007e283" id="uc007e283">如果你就是不想一直续期，那你就自己指定一个超时时间就行了。就不要用他的续期机制就好了。</span></p>
  <p data-lake-id="u15a2484d" id="u15a2484d"><span data-lake-id="ue51757e4" id="ue51757e4">​</span><br></p>
  <h3 data-lake-id="cJOKj" id="cJOKj"><span data-lake-id="ua7bd0da7" id="ua7bd0da7">一旦客户端挂了但是锁还没释放怎么办？</span></h3>
  <p data-lake-id="u1533cca6" id="u1533cca6"><br></p>
  <p data-lake-id="u56f23e0e" id="u56f23e0e"><span data-lake-id="uc33eff8a" id="uc33eff8a">如果，应用集群中的一台机器，拿到了分布式锁，但是在执行的过程中，他挂了，还没来得及把锁释放，那么会有问题么？</span></p>
  <p data-lake-id="u38d0cd34" id="u38d0cd34"><span data-lake-id="u876b1052" id="u876b1052">​</span><br></p>
  <p data-lake-id="u8784fb84" id="u8784fb84"><span data-lake-id="u1883829e" id="u1883829e">因为我们知道，锁的续期是Redisson实现的，而Redisson的后台任务是基于JVM运行的，也就是说，如果这台机器挂了，那么Redisson的后台任务也就没办法继续执行了。</span></p>
  <p data-lake-id="ua9a9ef3c" id="ua9a9ef3c"><span data-lake-id="u69f0588f" id="u69f0588f">​</span><br></p>
  <p data-lake-id="ucc415688" id="ucc415688"><span data-lake-id="ub27dd945" id="ub27dd945">那么他也就会再继续续期了，那么到了期限之后，锁就会自动解除了。这样就可以避免因为一个实例宕机导致分布式锁的不可用。</span></p>
  <p data-lake-id="uea8d3382" id="uea8d3382"><span data-lake-id="ufcd92622" id="ufcd92622">​</span><br></p>
  <h3 data-lake-id="CXZ6C" id="CXZ6C"><span data-lake-id="u0af7b739" id="u0af7b739">如果解锁失败了，怎么办？</span></h3>
  <p data-lake-id="uf8aa9182" id="uf8aa9182"><br></p>
  <p data-lake-id="u0428a6e2" id="u0428a6e2"><span data-lake-id="u8178ef2b" id="u8178ef2b">我们知道，Redisson如果没有主动解锁，就会一直续期，那么如果解锁过程中，失败了，怎么办呢？</span></p>
  <p data-lake-id="u772a6919" id="u772a6919"><span data-lake-id="u01b631c5" id="u01b631c5">​</span><br></p>
  <p data-lake-id="u73973b0f" id="u73973b0f"><span data-lake-id="u3110bbad" id="u3110bbad">如果真的是解锁失败了，那确实会导致锁无法被释放， 一直就被续期下去，直到这台机器重启。</span></p>
  <p data-lake-id="u413fc2b1" id="u413fc2b1"><span data-lake-id="u2bf4b8f5" id="u2bf4b8f5">​</span><br></p>
  <p data-lake-id="u3b9619d4" id="u3b9619d4"><span data-lake-id="u9732b452" id="u9732b452">但是，为了减少这种解锁失败的概率，一方面我们要把解锁的操作放到finally里面。</span></p>
  <p data-lake-id="uab7eed98" id="uab7eed98"><span data-lake-id="u4268abff" id="u4268abff">​</span><br></p>
  <p data-lake-id="ub7ae940f" id="ub7ae940f"><span data-lake-id="u43f165af" id="u43f165af">另外一方面，Redisson其实在接收到解锁请求的时候，并没有立即就去与Redis交互，而是会操作本地维护的</span><code data-lake-id="u7f943001" id="u7f943001"><span data-lake-id="u74218b54" id="u74218b54">EXPIRATION_RENEWAL_MAP</span></code><span data-lake-id="u3848d783" id="u3848d783">，会在unlock的时候操作的，对他进行remove，一旦这个步骤成功了，那么后续的续期操作也就不再进行了。</span></p>
  <p data-lake-id="ude26641f" id="ude26641f"><span data-lake-id="u52b126dd" id="u52b126dd">​</span><br></p>
  <p data-lake-id="u29e42f48" id="u29e42f48"><span data-lake-id="u9c3a5278" id="u9c3a5278">而在本地操作一个map失败的概率要比和远程的redis服务器交互失败的概率要小的多了。</span></p>
 </body>
</html>